import { Injectable, Logger, Inject, OnModuleInit } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { EventEmitter2 } from '@nestjs/event-emitter';
import { DynamicConfigService } from './dynamic-config.service';
import type { CacheInterface } from '../common/cache/cache.interface';

/**
 * WWJCloud 框架配置中心服务
 *
 * 职责：
 * - 管理 WWJCloud 框架级功能配置
 * - 为开发者提供开箱即用的企业级功能配置
 * - 支持动态配置、热更新、版本控制
 *
 * 注意：业务配置由 Core 层管理，这里只管理框架功能配置
 */
@Injectable()
export class ConfigCenterService implements OnModuleInit {
  private readonly logger = new Logger(ConfigCenterService.name);
  private readonly configWatchers = new Map<string, Set<Function>>();
  private readonly configVersions = new Map<string, number>();
  private isInitialized = false;

  constructor(
    private readonly configService: ConfigService,
    private readonly dynamicConfigService: DynamicConfigService,
    private readonly eventEmitter: EventEmitter2,
    @Inject('CACHE_PROVIDER')
    private readonly cache?: CacheInterface,
  ) {}

  async onModuleInit() {
    await this.initializeConfigCenter();
  }

  /**
   * 初始化配置中心
   */
  private async initializeConfigCenter(): Promise<void> {
    try {
      this.logger.log('初始化配置中心...');

      // 初始化框架配置
      await this.initializeFrameworkConfigs();

      // 启动配置监听
      this.startConfigWatching();

      this.isInitialized = true;
      this.logger.log('配置中心初始化完成');
    } catch (error) {
      this.logger.error('配置中心初始化失败', error);
      throw error;
    }
  }

  /**
   * 初始化 WWJCloud 框架配置
   * 为开发者提供开箱即用的框架功能配置
   */
  private async initializeFrameworkConfigs(): Promise<void> {
    try {
      // WWJCloud 框架配置中心：管理框架级功能配置
      // 为开发者提供开箱即用的企业级功能配置

      const defaultSiteId = 0;

      // WWJCloud 框架配置（对标 Java NiuCloud 的 ConfigKeyEnum）
      const frameworkConfigs = [
        // 对标 Java: NIUCLOUD_CONFIG("NIUCLOUD_CONFIG")
        { key: 'NIUCLOUD_CONFIG', value: '{}', addon: 'system' },

        // 对标 Java: WECHAT("WECHAT") - 微信公众号
        { key: 'WECHAT', value: '{}', addon: 'wechat' },

        // 对标 Java: WEAPP("weapp") - 微信小程序
        { key: 'weapp', value: '{}', addon: 'weapp' },

        // 对标 Java: WECHAT_PAY("wechat_pay") - 微信支付
        { key: 'wechat_pay', value: '{"status": 0}', addon: 'pay' },

        // 对标 Java: ALIPAY("alipay") - 支付宝支付
        { key: 'alipay', value: '{"status": 0}', addon: 'pay' },

        // 对标 Java: OFFLINE_PAY("offline_pay") - 线下支付
        { key: 'offline_pay', value: '{"status": 0}', addon: 'pay' },

        // 对标 Java: UPLOAD("upload") - 上传配置
        {
          key: 'upload',
          value: '{"type": "local", "max_size": 2048}',
          addon: 'upload',
        },

        // 对标 Java: SMS("SMS") - 短信配置 (PHP 中有定义)
        { key: 'SMS', value: '{"service_type": "aliyun"}', addon: 'sms' },

        // 对标 Java: ADMIN_LOGIN("admin_login") - 管理端登录注册设置
        { key: 'admin_login', value: '{}', addon: 'auth' },

        // 对标 Java: ALIAPP("aliapp") - 支付宝小程序
        { key: 'aliapp', value: '{}', addon: 'aliapp' },

        // 对标 Java: H5("h5") - h5配置
        { key: 'h5', value: '{}', addon: 'h5' },

        // 对标 Java: WXOPLATFORM("WXOPLATFORM") - 微信开放平台
        { key: 'WXOPLATFORM', value: '{}', addon: 'wechat' },

        // 对标 Java: DIY_BOTTOM("diy_bottom") - 底部导航配置
        { key: 'diy_bottom', value: '[]', addon: 'diy' },

        // 对标 Java: MEMBER_CASH_OUT("member_cash_out") - 会员提现
        { key: 'member_cash_out', value: '{}', addon: 'member' },
      ];

      for (const config of frameworkConfigs) {
        await this.dynamicConfigService.setConfig(
          defaultSiteId,
          config.key,
          config.value,
          config.addon,
        );
      }

      this.logger.log('WWJCloud 框架配置初始化完成');
    } catch (error) {
      this.logger.error('初始化框架配置失败', error);
    }
  }

  /**
   * 启动配置监听
   */
  private startConfigWatching(): void {
    // 定期检查配置变更
    setInterval(async () => {
      try {
        await this.checkConfigChanges();
      } catch (error) {
        this.logger.error('配置变更检查失败', error);
      }
    }, 30000); // 30秒检查一次
  }

  /**
   * 检查配置变更
   */
  private async checkConfigChanges(): Promise<void> {
    try {
      // 这里可以实现配置变更检测逻辑
      // 例如：检查数据库配置的更新时间
      this.logger.debug('检查配置变更...');
    } catch (error) {
      this.logger.error('配置变更检查失败', error);
    }
  }

  /**
   * 获取配置值（支持静态和动态配置）
   * @param key 配置键
   * @param defaultValue 默认值
   * @param siteId 站点ID
   * @returns 配置值
   */
  async getConfigValue<T = any>(
    key: string,
    defaultValue?: T,
    siteId: number = 0,
  ): Promise<T> {
    try {
      // 先尝试从动态配置获取
      const dynamicValue = await this.dynamicConfigService.getConfigValue<T>(
        siteId,
        key,
      );
      if (dynamicValue !== null) {
        return dynamicValue;
      }

      // 从静态配置获取
      const staticValue = this.configService.get<T>(key);
      if (staticValue !== undefined) {
        return staticValue;
      }

      return defaultValue as T;
    } catch (error) {
      this.logger.error(`获取配置失败: ${key}`, error);
      return defaultValue as T;
    }
  }

  /**
   * 设置配置值
   * @param key 配置键
   * @param value 配置值
   * @param siteId 站点ID
   * @param configType 配置类型
   * @param configGroup 配置分组
   */
  async setConfigValue(
    key: string,
    value: any,
    siteId: number = 0,
    addon: string = '',
  ): Promise<void> {
    try {
      await this.dynamicConfigService.setConfig(siteId, key, value, addon);

      // 触发配置变更事件
      this.eventEmitter.emit('config.changed', {
        siteId,
        key,
        value,
        timestamp: new Date(),
      });

      // 通知配置监听器
      this.notifyConfigWatchers(key, value);

      this.logger.log(`配置已更新: ${key} = ${value}`);
    } catch (error) {
      this.logger.error(`设置配置失败: ${key}`, error);
      throw error;
    }
  }

  /**
   * 删除配置值
   * @param key 配置键
   * @param siteId 站点ID
   */
  async deleteConfigValue(key: string, siteId: number = 0): Promise<void> {
    try {
      await this.dynamicConfigService.deleteConfig(siteId, key);

      // 触发配置删除事件
      this.eventEmitter.emit('config.deleted', {
        siteId,
        key,
        timestamp: new Date(),
      });

      this.logger.log(`配置已删除: ${key}`);
    } catch (error) {
      this.logger.error(`删除配置失败: ${key}`, error);
      throw error;
    }
  }

  /**
   * 刷新配置缓存
   * @param siteId 站点ID
   * @param key 配置键（可选）
   */
  async refreshConfigCache(siteId: number = 0, key?: string): Promise<void> {
    try {
      await this.dynamicConfigService.refreshConfigCache(siteId, key);

      // 触发配置刷新事件
      this.eventEmitter.emit('config.refreshed', {
        siteId,
        key,
        timestamp: new Date(),
      });

      this.logger.log(`配置缓存已刷新: ${siteId}:${key || 'all'}`);
    } catch (error) {
      this.logger.error(`刷新配置缓存失败: ${siteId}:${key}`, error);
      throw error;
    }
  }

  /**
   * 推送配置变更
   * @param siteId 站点ID
   * @param key 配置键
   * @param value 配置值
   */
  async pushConfigChange(
    siteId: number,
    key: string,
    value: any,
  ): Promise<void> {
    try {
      // 触发配置推送事件
      this.eventEmitter.emit('config.pushed', {
        siteId,
        key,
        value,
        timestamp: new Date(),
      });

      // 通知配置监听器
      this.notifyConfigWatchers(key, value);

      this.logger.log(`配置已推送: ${key} = ${value}`);
    } catch (error) {
      this.logger.error(`推送配置失败: ${key}`, error);
      throw error;
    }
  }

  /**
   * 注册配置监听器
   * @param key 配置键
   * @param callback 回调函数
   */
  registerConfigWatcher(key: string, callback: Function): void {
    if (!this.configWatchers.has(key)) {
      this.configWatchers.set(key, new Set());
    }
    this.configWatchers.get(key)?.add(callback);

    this.logger.log(`注册配置监听器: ${key}`);
  }

  /**
   * 取消配置监听器
   * @param key 配置键
   * @param callback 回调函数
   */
  unregisterConfigWatcher(key: string, callback: Function): void {
    const watchers = this.configWatchers.get(key);
    if (watchers) {
      watchers.delete(callback);
      if (watchers.size === 0) {
        this.configWatchers.delete(key);
      }
    }

    this.logger.log(`取消配置监听器: ${key}`);
  }

  /**
   * 通知配置监听器
   * @param key 配置键
   * @param value 配置值
   */
  private notifyConfigWatchers(key: string, value: any): void {
    const watchers = this.configWatchers.get(key);
    if (watchers) {
      for (const callback of watchers) {
        try {
          callback(key, value);
        } catch (error) {
          this.logger.error(`配置监听器执行失败: ${key}`, error);
        }
      }
    }
  }

  /**
   * 获取配置版本信息
   * @param siteId 站点ID
   * @param key 配置键
   * @returns 版本信息
   */
  async getConfigVersion(siteId: number, key: string): Promise<number> {
    try {
      const history = await this.dynamicConfigService.getConfigHistory(
        siteId,
        key,
      );
      return history.length > 0 ? history[0].updateTime : 0;
    } catch (error) {
      this.logger.error(`获取配置版本失败: ${key}`, error);
      return 0;
    }
  }

  /**
   * 回滚配置到指定版本
   * @param siteId 站点ID
   * @param key 配置键
   * @param version 版本号
   */
  async rollbackConfig(
    siteId: number,
    key: string,
    version: number,
  ): Promise<void> {
    try {
      await this.dynamicConfigService.rollbackConfig(siteId, key, version);

      // 触发配置回滚事件
      this.eventEmitter.emit('config.rolledback', {
        siteId,
        key,
        version,
        timestamp: new Date(),
      });

      this.logger.log(`配置已回滚: ${key} 到版本 ${version}`);
    } catch (error) {
      this.logger.error(`回滚配置失败: ${key}:${version}`, error);
      throw error;
    }
  }

  /**
   * 热重载配置
   * @param siteId 站点ID
   * @param key 配置键（可选）
   */
  async hotReloadConfig(siteId: number = 0, key?: string): Promise<void> {
    try {
      // 刷新配置缓存
      await this.refreshConfigCache(siteId, key);

      // 触发热重载事件
      this.eventEmitter.emit('config.hotreloaded', {
        siteId,
        key,
        timestamp: new Date(),
      });

      this.logger.log(`配置热重载完成: ${siteId}:${key || 'all'}`);
    } catch (error) {
      this.logger.error(`配置热重载失败: ${siteId}:${key}`, error);
      throw error;
    }
  }

  /**
   * 获取配置中心状态
   * @returns 状态信息
   */
  getConfigCenterStatus(): any {
    return {
      isInitialized: this.isInitialized,
      watcherCount: this.configWatchers.size,
      totalWatchers: Array.from(this.configWatchers.values()).reduce(
        (sum, set) => sum + set.size,
        0,
      ),
      uptime: Date.now(),
    };
  }
}
